iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0

delete可以幫助我們刪除所有的object。其用法和select非常相近,而事實上delete其實是delete (select ...)語法糖

我們繼續使用[Day03]中定義的schema

type User {
    required name: str;
    multi followers: User;
}

type Article {
    required title: str;
    required author: User;
}

執行下列query生成兩個Article object及四個User object

insert Article {
   title:= "first article",
   author:= (insert User {name:= "John"})
};

insert Article {
   title:= "second article",
   author:= (insert User {name:= "Jeff"})
};

for name in {"Tom", "Cathy"}
union (insert User {name:= name});

以下我將以CathyJohnTomJeff來簡單稱呼其name property分別為「"Cathy"」、「"John"」、「"Tom"」與「"Jeff"」的User object

Delete

假設現在我們想刪除tom,可以這麼寫:

delete User filter .name="Tom";

delete是一個很重要的操作,通常會先使用select來確認所選到object是否符合:

select User filter .name="Tom";

確認選擇無誤後,再將select換成delete

如果是面對比較複雜的query時,會建議在with中建立中間變數,像是:

with tom:= (select User filter .name="Tom")
select tom {name};

確認選擇無誤後,再將select換成delete

with tom:= (select User filter .name="Tom")
delete tom {name};

Bulk delete

如果我們想要刪掉所有的object,您可能會很直覺的想要使用for-loop。但別忘了,deletedelete (select ...)的語法糖,所以回想一下我們是怎麼使用select選擇object的呢?沒錯,直接select就好,所以bulk delete最快的方法是,使用select確認選擇無誤:

select User;
select Article;

再將select換成delete

delete User;
delete Article;

Deletion police

delete是一個頗為複雜的主題,有可能需要針對每一個object type,制訂不同的deletion policeEasy EdgeDB第十三章中有提到一些可能遇到的複雜情況。

deletion police可以分為target deletionsource deletion兩種。

其中target deletion有:

  • restrict(預設)。
  • delete source
  • allow
  • deferred restrict

source deletion有:

  • allow
  • delete target
  • delete target if orphan

我們這邊舉幾個常用的情況供大家參考。

on target delete restrict

由於on target delete restrict是預設,所以目前User object的schema與下面的schema其實是相同的:

type User {
    required name: str;
    multi followers: User {
        on target delete restrict;
    };
}

這個deletion police是指當有一個User object連接到其它User objectmulti followers link時,這個User object是無法被刪除的。

舉例來說,如果我們將JohnTom指定為Jeffmulti followers link

with jeff:= (select User filter .name="Jeff"),
     followers:= (select User filter .name in {"John", "Tom"})
update jeff
set {
    followers:= followers
};

假設此時我們試圖delete John

delete User filter .name="John";

會報錯如下:

edgedb error: ConstraintViolationError: deletion of default::User (988d4658-5248-11ef-af3f-b785e4ec0502) is prohibited by link target policy
Detail: Object is still referenced in link followers of default::User (988d46d0-5248-11ef-af3f-57711cc00e48).

因為John仍在Jeffmulti followers link中。

on target delete delete source

此時如果將delete policy改為on target delete delete source

type User {
    required name: str;
    multi followers: User {
        on target delete delete source;
    };
}

這個deletion police是指當有一個User object連接到其它User objectmulti followers link時,如果這個User object被刪除的話,與其連接的User object也會被刪除。

此時我們可以刪除John

delete User filter .name="John";

再確認剩下哪些User object

select User {name, followers};
{
    default::User {
        name: 'Cathy', 
        followers: {}
    }, 
    default::User {
        name: 'Tom', 
        followers: {}
    }
}

可以發現只剩下CathyTom。這是因為當我們刪除Johntarget)時,也會刪除Jeffsource)。

on source delete delete target

接著我們將delete policy改為on source delete delete target

type User {
    required name: str;
    multi followers: User {
        on source delete delete target;
    };
}

並重新insertJohnJeff

for name in {"John", Jeff"}
union (insert User {name:= name});

並將JohnTom指定為Jeffmulti followers link

with jeff:= (select User filter .name="Jeff"),
     followers:= (select User filter .name in {"John", "Tom"})
update jeff
set {
    followers:= followers
};

這個deletion police是指當有一個User object被刪除時,與其multi followers link所連接的User object也會被刪除。

此時我們可以刪除Jeff

delete User filter .name="Jeff";

再確認剩下哪些User object

select User {name, followers};
{default::User {name: 'Cathy', followers: {}}}

可以發現只剩下Cathy。這是因為當我們刪除Jeffsource)時,也會刪除JohnTomtarget)。


上一篇
[Day05] - 如何update
下一篇
[Day07] - 介紹multi property及array
系列文
一起看無間道學EdgeDB30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言